package epam.car.rent;

import epam.car.rent.exceptions.CarException;



enum CarType {
	ECONOMY("4-Cylinder Engine", "2 large persons, 2 small persons, 2 small suitcase"),
	COMPACT("4-Cylinder Engine", "2 large persons, 1 medium person, 2 small persons, 1 large suitcase, 2 small suitcase"),
	MIDSIZE("4 or 6-Cylinder Engine", "2 large persons, 2 medium persons, 1 small person, 2 large suitcase, 2 small suitcase"),
	FULLSIZE("6-Cylinder Engine", "2 large persons, 2 medium persons, 1 small person, 2 large suitcase, 3 small suitcase"),
	PREMIUM("6-Cylinder Engine", "5 large persons, 1 small person, 3 large suitcase, 2 small suitcase"), 
	MINIVAN("6-Cylinder Engine", "6 large persons, 1 medium person, 3 large suitcase, 1 small suitcase"),
	CONVERTIBLE("4 or 6-Cylinder Engine", "2 large persons, 2 small person, 1 small suitcase"), 
	SPORTUTILITY("6-Cylinder Engine", "4 large persons, 1 medium person, 4 large suitcase, 3 small suitcase"), 
	LUXURY("6 or 8-Cylinder Engine", "6 large persons, 4 large suitcase, 2 small suitcase");

	private String engine;
	private String capacity;

	private CarType(String engine, String capacity) {
		this.engine = engine;
		this.capacity = capacity;
	}

	/**
	 * ����� ��������� ������ ������ � ���������, ������� ��������������� �� ���
	 * ��������� �����
	 * 
	 * @return ������ ������, ���������� ���������� � ���������
	 */
	public String getEngine() {
		return this.engine;
	}

	/**
	 * ����� ��������� ������ ������ � ��������������� ����� ���� �����
	 * 
	 * @return ������ ������, ���������� ���������� � ��������������� ������
	 */
	public String getCapacity() {
		return this.capacity;
	}

	/**
	 * 
	 * @return ���������� ��� ������.
	 */
	public CarType getType() {
		return this;
	}

}

/**
 * This class describes a car entity in this system.
 * 
 * @author Alexander Tretyak
 * 
 */
public class Car extends Management {
	/**
	 * The inner class that incapsulates information about car model, price and car type.
	 * 
	 * @author Alexander Tretyak
	 * @version 1.0
	 * 
	 */
	private static class Model {
		
		private String automodel;
		private double price;
		private CarType carType;

		public String getModel() {
			return this.automodel;
		}

		public Model(String aModel, double aPrice, CarType carType)
				throws CarException {
			this.automodel = aModel;
			if (aPrice > 0) {
				this.price = aPrice;
			} else {
				throw new CarException(
						"Price of the car must be more than zero! \n");
			}
			this.carType = carType;
		}
	}

	private Model model;

	private long carId;
	//private int rentFor;
	private Client rentBy;
	private Damages damages;

	/**
	 * Constructor for class Car.
	 * 
	 * @param aModel
	 * @param aPrice
	 * @param carType
	 * @throws CarException
	 */
	public Car(String aModel, double aPrice, String carType)
			throws CarException {
		carType = carType.toUpperCase();
		try {
			model = new Model(aModel, aPrice, CarType.valueOf(carType));
		} catch (NumberFormatException e) {
			throw new CarException("The price must be a float! \n");
		} catch (IllegalArgumentException e) {
			throw new CarException("Please fill in an acceptable car type! \n");
		}
		this.rentBy = null;
		//this.rentFor = 0;
		setDamages(Damages.NONE);
		this.carId = formId();
	}

	public void setCarId(long id) {
		this.carId = id;
	}

	public long getId() {
		return carId;
	}

	/**
	 * This method returns an object of class Client if a car is rent by somebody.
	 * 
	 * @return Client {@link Client}
	 */
	public Client getRentBy() {
		if (this.rentBy == null) {
			// System.out.println("A car isn't leased.");
			return null;
		} else
			return rentBy;
	}

	/**
	 * Set up a client that rent a car
	 * 
	 * @param rentBy
	 *            
	 */
	public void setRentBy(Client rentBy) {
		this.rentBy = rentBy;
	}

	/**
	 * Informs about damages. {@link Damages}
	 */
	public Damages getDamages() {
		return this.damages;
	}

	/**
	 * Set damages for car
	 * 
	 * See also {@link Damages}
	 * @param damage
	 */
	public void setDamages(Damages damage) {
		this.damages = damage;
	}

	/**
	 * Returns a name of the car model
	 */
	public String getModel() {
		return this.model.getModel();
	}

	/**
	 * returns price
	 */
	public double getPrice() {
		return this.model.price;
	}

	/**
	 * Let's to know the information about engine.
	 * See also {@link CarType}
	 * @return Engine details
	 */
	public String getEngineDetails() {
		return this.model.carType.getEngine();
	}
	/**
	 * Returns the capacity information for this kind of car.
	 * See {@link CarType}
	 * @return
	 */
	public String getCapasityDetails() {
		return this.model.carType.getCapacity();
	}

	/**
	 * Returns the car type
	 * See {@link CarType}
	 */
	public CarType getCarType() {
		return this.model.carType.getType();
	}
	/**
	 * Converts general information about a car into string.
	 * 
	 * Parametrized method toString returns tab-delimited stirng
	 * 
	 * @param param
	 * @return
	 */
	public String toString(String param) {
		String result = this.carId + "\t" + this.getModel() + "\t"
				+ this.getPrice() + "\t" + this.getCarType() + "\t"
				+ getDamages() + "\t" + this.getRentBy() + "\t";
		return result;
	}

	/**
	 * Human-readable method toString.
	 * It's used for outputting information about a car on display or UI
	 */
	
	public String toString() {
		String result = "";
		result = this.carId + " " + this.getModel() + " (price is "
				+ this.getPrice() + "). ";
		result += "Category is " + this.getCarType() + ". ";
		result += (this.getDamages() != Damages.NONE) ? "Has "
				+ this.getDamages() + " damages." : "Has no damages. ";

		if (getRentBy() != null) {
			result += "Rent by " + this.getRentBy().getName();
		} else {
			result += "Is not rent by anybody";
		}
		return result;

	}
}
